using System;
using System.Diagnostics;
using System.IO;

namespace SaveGameConverter
{
    class Program
    {
        private static readonly string _separator = "".PadLeft(Console.BufferWidth - 1, '-');

        static void Main(string[] args)
        {
            try
            {
                Arguments arguments = ParseArgs(args);
                switch (arguments.Mode)
                {
                    case Mode.ToXml:
                        Save2Xml.Convert(arguments.SourceFile, arguments.TargetFile);
                        break;
                    case Mode.ToSave:
                        Xml2Save.Convert(arguments.SourceFile, arguments.TargetFile);
                        break;
                    default:
                        throw new Exception("Abnormal error.");
                }

                Environment.Exit(0);
            }
            catch (Exception ex)
            {
                Console.WriteLine(_separator);
                Console.WriteLine(ex);
                Console.WriteLine(_separator);
                WaitingForAnyKey();

                Environment.Exit(1);
            }
        }

        private static Arguments ParseArgs(string[] args)
        {
            if (args.Length != 1)
            {
                ExitWithHelp();
                return null;
            }

            string filePath = args[0];
            if (string.IsNullOrEmpty(filePath))
                throw new ArgumentException("Emprty file path.");

            string ext = Path.GetExtension(filePath).ToLower();

            Mode mode;
            switch (ext)
            {
                case ".save":
                    mode = Mode.ToXml;
                    break;
                case ".xml":
                    mode = Mode.ToSave;
                    break;
                default:
                    throw new ArgumentException("Unknown file extension: " + ext);
            }

            if (!File.Exists(filePath))
            {
                if (Path.GetFileName(filePath) != filePath)
                    throw new FileNotFoundException(filePath);

                filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "MightAndMagicXLegacy", filePath);
                if (!File.Exists(filePath))
                    throw new FileNotFoundException(filePath);
            }

            return new Arguments(filePath, mode);
        }

        private static void ExitWithHelp()
        {
            Console.WriteLine(_separator);
            Console.WriteLine("SaveGameConverter v{0} Albeoris (c) 2013-2014", Process.GetCurrentProcess().GetType().Assembly.GetName().Version);
            Console.WriteLine("Converts the file saved game Might & Magic X to XML or XML to a file saved game.");
            Console.WriteLine();
            Console.WriteLine("Save games path:");
            Console.WriteLine(@"C:\Program Files (x86)\Ubisoft\Ubisoft Game Launcher\savegames\?\403");
            Console.WriteLine();
            Console.WriteLine("{0} save|xml", Process.GetCurrentProcess().ProcessName);
            Console.WriteLine();
            Console.WriteLine("	save\tThe absolute or relative path or file name of saved game.");
            Console.WriteLine("	xml\tThe absolute or relative path or file name of XML.");
            Console.WriteLine(_separator);
            WaitingForAnyKey();

            Environment.Exit(255);
        }

        private static void WaitingForAnyKey()
        {
            Console.WriteLine("Press any key...");
            Console.ReadKey();
        }

        private sealed class Arguments
        {
            public readonly string SourceFile;
            public readonly string TargetFile;
            public readonly Mode Mode;

            public Arguments(string filePath, Mode mode)
            {
                if (filePath == null)
                    throw new ArgumentNullException("filePath");

                SourceFile = filePath;
                TargetFile = Path.ChangeExtension(filePath, mode == Mode.ToSave ? ".save" : ".xml");
                Mode = mode;
            }
        }

        private enum Mode
        {
            ToXml,
            ToSave
        }
    }
}
